import re
from nodetypes import config

from myelin.server.core.ft import ModelDriver
from myelin.rdf.stores.ft import LimitAdapter
from myelin.server.lib.RdfQueryResolvers import GraphResolver, TextIndexResolver


class Query:
    
    defaults = config.QUERY_DEFAULTS
    nsMapPatSplit = re.compile(r'\s*([\w]+)\s*=\s*([\'\"]*)([^\"\'\s]+)\2\s*').split
        
    newGraphResolver = staticmethod(GraphResolver.FromRepo)    
    newDefaultAdapter = staticmethod(ModelDriver.FromRepo)
    newTextIndexResolver = TextIndexResolver
    newLimitAdapter = LimitAdapter.LimitAdapter
    newLimit = LimitAdapter.Limit
               
    
    def getQueryLimit(self, repo, account, defaults):
        acct = context.account
        if acct.isAdmin:
            return
        
        if acct.isAgent():
            return self.newLimit(
                int(
                    getattr(
                        defaults,'user_query_limit',None
                    ) or self.defaults['user-query-limit']
                )
            )
            
        return self.newLimit(
            int(
                getattr(
                    defaults,'guest_query_limit',None
                ) or self.defaults['guest-query-limit']
            )
        )    
    
    def getDbSource(self, repo, config, account, acls, defaults):
        F = repo._driver.getResourcePath
        dqg = map(F,config.defaultRdfGraphs.iterkeys())
        
        db = self.newDefaultAdapter(
            repo, dqg
        )
            
        if account.isAdmin:
            F = repo._driver.getResourcePath
            rs = self.newGraphResolver(
                repo,
                lambda d: d,
                acls,
                dict((k,[F(k)]) for k in config.rdfGraphs.iterkeys())
            )
            
        else:
            if account.isAgent():
                l = self.newLimit(
                    int(
                        config.params.get((None,'user-query-limit')) or
                        self.defaults['user-query-limit']
                    )
                )
            else:
                l = self.newLimit(
                    int(
                        config.params.get((None,'guest-query-limit')) or
                        self.defaults['guest-query-limit']
                    )
                )
            
            
            rs = lambda n, a=acls.checkNodeAcls: a(n,'query')            
            rs = self.newGraphResolver(
                repo,
                lambda d, c=self.newLimitAdapter, l=l, f=rs: c(d,l,f),
                acls,
                dict((k,[F(k)]) for k in config.rdfGraphs.iterkeys())           
            )
            
        ir = self.newTextIndexResolver(
            repo,
            config.textIndices,
            lambda r,a=acls.checkNodeAcls: a(r[0])
        )
        
        return db, dqg, rs, ir
    
    def splitNsMaps(self, nsString, nsMaps):
        m = self.nsMapPatSplit(nsString)
        if m:
            l = len(m)
            i = 0
            while i+3 < l:
                if m[i]:
                    return 'invalid-token'
                ns = m[i+1]
                if not ns:
                    return 'invalid-ns'
                url = m[i+3]
                if not url:
                    return 'invalid-url'
                    break
                nsMaps[ns] = url
                i += 4
            i -= l
            if i == -1:
                #print "m-1: %s" % m[-1]
                if m[-1]:
                    return 'invalid-token'
            elif i < 4: # checks for garbage at the end
                return 'invalid-token'
            
del re, \
    config, \
    LimitAdapter, \
    ModelDriver